#include <asm/cpuid.h>
#include <pub.h>

#define __CUPID_BASE(no, a, b, c, d)         \
    __asm__ __volatile__(                    \
        "cpuid"                              \
        : "=a"(a), "=b"(b), "=c"(c), "=d"(d) \
        : "a"(no))

u32_t query_base() // index:0
{
    register u32_t a;
    register u32_t b;
    register u32_t c;
    register u32_t d;

    __CUPID_BASE(0, a, b, c, d);

    return a;
}

u32_t query_ext() // index:0x80000000
{
    register u32_t a;
    register u32_t b;
    register u32_t c;
    register u32_t d;

    __CUPID_BASE(0x80000000, a, b, c, d);

    return a;
}

u8_t max_phy_addr() {
    register u32_t a;
    register u32_t b;
    register u32_t c;
    register u32_t d;

    __CUPID_BASE(0x80000008, a, b, c, d);

    return (u8_t)(a & 0xff);
}

u32_t is_enable_xd() {
    register u32_t a;
    register u32_t b;
    register u32_t c;
    register u32_t d;

    __CUPID_BASE(0x80000001, a, b, c, d);

    return (d >> 20) & 0x01;
}

u32_t check_long_mod() {
    register u32_t a;
    register u32_t b;
    register u32_t c;
    register u32_t d;

    __CUPID_BASE(0x80000001, a, b, c, d);

    return (d >> 29) & 0x01;
}

u32_t is_enable_1g_page() {
    register u32_t a;
    register u32_t b;
    register u32_t c;
    register u32_t d;

    __CUPID_BASE(0x80000001, a, b, c, d);

    return (d >> 26) & 0x01;
}

u32_t check_pcids() {
    register u32_t a;
    register u32_t b;
    register u32_t c;
    register u32_t d;

    __CUPID_BASE(0x01, a, b, c, d);

    return (c >> 17) & 0x01;
}